﻿using System;
using System.Xml;
using System.Xml.Linq;
using XmlStudio.DataLayer;
using XmlStudio.Interfaces;

namespace XmlStudio.Utilities {
    /// <summary>
    /// Helper class which builds tree hierarchy from string and adjusts addresses of some node.
    /// </summary>
    internal class TreeBuilder {
        #region Methods
        #region Public
        /// <summary>
        /// Builds tree hierarchy for xml from string.
        /// </summary>
        /// <param name="xml">String with xml.</param>
        /// <returns>Reference to the root node.</returns>
        public static BigXmlNodeInternal BuildTree(string xml) {
            XElement root = XElement.Parse(xml);

            BigXmlNodeInternal rootNode = BigXmlNodeInternal.Create(null, new[] { 1 }, null); //new MyBigXmlNode(new int[] { 1 });
            //rootNode.TotalChildCount = 0;
            rootNode.XmlNode = root.GetXmlNode().ChildNodes[0];

            AddChildNodes(rootNode);

            return rootNode;
        }

        /// <summary>
        /// Adjusts the addresses beneath the parent node according to the parent's address.
        /// </summary>
        /// <param name="parent">Parent node.</param>
        /// <param name="model">The model.</param>
        public static void AdjustAddresses(BigXmlNodeInternal parent, IXmlModel model) {
            int i = 1;
            foreach(var child in parent.ChildNodes) {
                var address = new int[parent.Address.Length + 1];
                Array.Copy(parent.Address, address, parent.Address.Length); // copy address from parent
                address[parent.Address.Length] = i;

                if(child != null) {
                    //if (xmlModel != null)
                    //{
                    //    if (child.Address != null && xmlModel.Nodes.ContainsKey(child.Address))
                    //    {
                    //        xmlModel.Nodes.Remove(child.Address);
                    //    }
                    //}

                    ((BigXmlNodeInternal)child).SetAddress(address);

                    //if (xmlModel != null)
                    //{
                    //    if (child.Address != null)
                    //    {
                    //        xmlModel.Nodes.Add(child.Address, child);
                    //    }
                    //}

                    AdjustAddresses(child as BigXmlNodeInternal, model);
                }

                i++;
            }
        }
        #endregion

        #region Private
        private static void AddChildNodes(BigXmlNodeInternal parent) {
            foreach(XmlNode child in ((XmlNode)parent.XmlNode).ChildNodes) // TODO use XPathNavigator's functionality
            {
                BigXmlNodeInternal childNode = BigXmlNodeInternal.Create(child);
                //childNode.TotalChildCount = 0;
                parent.ChildNodes.Add(childNode);
                childNode.SetParent(parent);
                AddChildNodes(childNode);
            }
        }
        #endregion
        #endregion
    }
}